package com.specialprice.business;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.logging.Logger;

import javax.jdo.PersistenceManager;
import javax.jdo.Query;
import javax.jdo.Transaction;

import nimnaw.appengine.base.datastore.PMF;

import com.google.appengine.api.datastore.KeyFactory;
import com.specialprice.model.Product;
import com.specialprice.model.ProductPrice;

public class SaveProductBusiness {
	private static final Logger log = Logger
			.getLogger(SaveProductBusiness.class.getName());

	private PersistenceManager pm = PMF.get().getPersistenceManager();

	private void save(Product p, Product o, boolean isPriceChanged,
			boolean isDateChanged) {

		long id = p.getId();

		List<Object> saveList = new ArrayList<Object>(3);

		if (isPriceChanged || isDateChanged) {
			if (o != null) {
				Date oldTimestamp = o.getTimestamp();
				Date lastPriceTimestamp = o.getLastPriceTimestamp();
				if (lastPriceTimestamp == null
						|| oldTimestamp.after(lastPriceTimestamp)) {
					String oldPriceKey = KeyFactory
							.keyToString(new KeyFactory.Builder(
									Product.SIMPLE_NAME, id).addChild(
									ProductPrice.SIMPLE_NAME,
									oldTimestamp.getTime()).getKey());

					ProductPrice oldPriceEntry = new ProductPrice();
					oldPriceEntry.setKey(oldPriceKey);
					oldPriceEntry.setId(id);
					oldPriceEntry.setPrice(o.getPrice());
					oldPriceEntry.setTimestamp(oldTimestamp);

					o.setLastPriceTimestamp(oldTimestamp);
					
					saveList.add(oldPriceEntry);
				}
			}
		}

		if (isPriceChanged) {
			Date newtimestamp = p.getTimestamp();

			// product price entry
			String newPriceKey = KeyFactory.keyToString(new KeyFactory.Builder(
					Product.SIMPLE_NAME, id).addChild(ProductPrice.SIMPLE_NAME,
					newtimestamp.getTime()).getKey());

			ProductPrice newPriceEntry = new ProductPrice();
			newPriceEntry.setKey(newPriceKey);
			newPriceEntry.setId(id);
			newPriceEntry.setPrice(p.getPrice());
			newPriceEntry.setTimestamp(newtimestamp);

			saveList.add(newPriceEntry);

			p.setLastPriceTimestamp(newtimestamp);
		} else {
			if (o != null) {
				p.setLastPriceTimestamp(o.getLastPriceTimestamp());
			}
		}

		saveList.add(p);

		pm.makePersistentAll(saveList);
	}

	private long deleteOldProductPriceBefore(long id, Date date) {

		Query q = pm.newQuery(ProductPrice.class);
		q.declareImports("import java.util.Date");
		q.declareParameters("Long idParam, Date timestampParam");
		q.setFilter("id == idParam && timestamp < timestampParam");

		try {
			return q.deletePersistentAll(id, date);
		} finally {
			q.closeAll();
		}
	}

	public void save(Product p, Product o, boolean isPriceChanged,
			boolean isDateChanged, Date minDate) {

		Transaction tx = pm.currentTransaction();
		try {
			tx.begin();

			// save Product & ProductPrice
			save(p, o, isPriceChanged, isDateChanged);

			if (isDateChanged) {
				// delete old prices from datastore
				deleteOldProductPriceBefore(p.getId(), minDate);
			}

			tx.commit();
		} finally {
			if (tx.isActive()) {
				tx.rollback();
			}
			pm.close();
		}
	}
}
